1 module unde.main;
2 
3 import unde.draw;
4 import unde.global_state;
5 import unde.tick;
6 import unde.slash;
7 import unde.games.dizzy.omega.main;
8 import unde.games.obj_splitter;
9 import unde.games.obj_joiner;
10 import unde.games.obj_loader;
11 import unde.games.obj_writer;
12 
13 import derelict.sdl2.sdl;
14 
15 import std.stdio;
16 import std.file;
17 import std.conv;
18 import core.stdc.stdlib;
19 
20 import core.sys.posix.signal;
21 
22 void split_scene()
23 {
24     writefln("Load scene");
25     auto scene1 = load_objfile("models/scene-01.obj");
26     writefln("Split");
27     auto scenes1 = split_objfile(scene1);
28     writefln("Write scenes");
29     foreach(sc, scene; scenes1)
30     {
31         if (sc in screen_names)
32             save_objfile(scene);
33     }
34 
35     writefln("Load scene");
36     auto scene2 = load_objfile("models/scene-02.obj");
37     writefln("Split");
38     auto scenes2 = split_objfile(scene2);
39     writefln("Write scenes");
40     foreach(sc, scene; scenes2)
41     {
42         if (sc in screen_names && (sc !in scenes1 ||
43             scene.objects.length > scenes1[sc].objects.length))
44             save_objfile(scene);
45     }
46 
47     writefln("Load solid scenes");
48     auto scene1solid = load_objfile("models/scene-01-solid.obj");
49     auto scene2solid = load_objfile("models/scene-02-solid.obj");
50     writefln("Join");
51     scene1solid.join_objfiles(scene2solid);
52     scene1solid.filename = "models/scene-solid.obj";
53     scene1solid.mtl.filename = "models/scene-solid.mtl";
54     writefln("Write solid scene");
55     save_objfile(scene1solid);
56 
57     writefln("Load dangers scenes");
58     auto scene1dangers = load_objfile("models/scene-01-dangers.obj");
59     auto scene2dangers = load_objfile("models/scene-02-dangers.obj");
60     writefln("Join");
61     scene1dangers.join_objfiles(scene2dangers);
62     scene1dangers.filename = "models/scene-dangers.obj";
63     scene1dangers.mtl.filename = "models/scene-dangers.mtl";
64     writefln("Write dangers scene");
65     save_objfile(scene1dangers);
66 
67 }
68 
69 extern(C) void mybye(int value){
70     exit(1);
71 }
72 
73 int main(string[] args)
74 {
75     bool scene_splitter;
76     size_t display;
77 
78     for (int i=1; i < args.length; i++)
79     {
80         if (args[i] == "--scene-splitter")
81         {
82             scene_splitter = true;
83         }
84         else if (args[i] == "--display")
85             display = args[++i].to!size_t;
86     }
87 
88     if (scene_splitter)
89     {
90         split_scene();
91         return 0;
92     }
93 
94     GlobalState gs = new GlobalState(false, display);
95     version(Posix)
96     {
97         sigset(SIGINT, &mybye);
98         
99         sigset_t set;
100         sigaddset(&set, SIGPIPE);
101         int retcode = sigprocmask(SIG_BLOCK, &set, null);
102         if (retcode == -1) throw new Exception("sigprocmask error");
103     }
104 
105     /* How many frames was skipped */
106     uint skipframe;
107     /* How long rendering was last frame */
108     uint last_draw_time;
109     uint[] times;
110     uint prev_time;
111 
112     /* Sum of time which was taken by rendering */
113     uint drawtime;
114     /* Minumum time between 2 frames */
115     uint min_frame_time = 2;
116     /* Maximum skip frames running */
117     uint max_skip_frames = 10;
118 
119     /* Start time used in below scope(exit) to calculate avarage
120        rendering time*/
121     uint starttime=SDL_GetTicks();
122     scope(exit)
123     {
124         uint endtime = SDL_GetTicks();
125         writefln("FPS= %f, average draw time: %f ms",
126             (cast(float)gs.frame)*1000/(endtime-starttime), 
127             (cast(float)drawtime)/gs.frame);
128         /* EN: Necessary because otherwise it will destroy 
129            gs.dbenv, gs.db_map before and it lead to Seg.Fault
130            RU: Необходим, т.к. иначе до gs будут уничтожены
131            gs.dbenv, gs.db_map, что ведёт к ошибке сегментирования */
132         destroy(gs);
133     }
134 
135     /* The main Idea of rendering process:
136        Splitting the actions which must be done on frame on 2:
137        1. Process events and make tick
138        2. Draw Frame
139        "Draw frame" maybe skipped to catch up real time,
140        But "Make tick" can't be skipped
141      */
142     while(!gs.finish)
143     {
144         uint time_before_frame=SDL_GetTicks();
145 
146         /* Process incoming events. */
147 
148         process_events(gs);
149 
150         make_tick(gs);
151         stdout.flush();
152 
153         uint now=SDL_GetTicks();
154         /* Draw the screen. */
155         /* Don't skip frame when:
156             1. Too much frame skipped
157             2. The virtual time (gs.time) too big (more than real time)
158             3. Estimation time of the next frame less than minimum frame time  */
159         if ( skipframe>=max_skip_frames || (gs.time+250.0)>now ||
160                 (now+last_draw_time)<(time_before_frame+min_frame_time) )
161         {
162             uint time_before_draw=SDL_GetTicks();
163 
164             if (gs.window_shown)
165                 draw_screen(gs);
166 
167             last_draw_time=SDL_GetTicks()-time_before_draw;
168             drawtime+=last_draw_time;
169 
170             //gs.txn.commit();
171 
172             gs.frame++;
173             skipframe=0;
174         }
175         else skipframe++;
176 
177         now=SDL_GetTicks();
178 
179         /* Calculate FPS */
180         gs.fps_frames++;
181         gs.fps_time += now - prev_time;
182         times ~= now - prev_time;
183         if (gs.fps_frames > 100)
184         {
185             gs.fps_time -= times[0];
186             gs.fps_frames--;
187             times = times[1..$];
188         }
189         prev_time = now;
190         
191         /* Virtual time more real time? */
192         if (gs.time>now)
193             SDL_Delay(gs.time-now);
194         else /* If time of frame too small */
195             if ( (now - time_before_frame)<min_frame_time )
196                 SDL_Delay( min_frame_time - (now - time_before_frame) );
197         
198         /* Add 10 ms to time, because we want render with speed 100 FPS
199            1 frame / 100 FPS = 1/100s = 10ms */
200         gs.time += 10;
201 
202     }
203     return 0;
204 }